package Gui;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

import javax.swing.*;

import GameEngine.GameMessage;
import GameEngine.GameSettings;
import GameEngine.Message;
import GameEngine.Move;
import GameEngine.Status;

public class GameGUI {
	private static final long serialVersionUID = 1L;

	/* GRAPHICS SWING COMPONENT */
	private DrawingPanel drawingArea;
	private JFrame gameFrame;
	private JFrame rules;
	private JFrame credits;

	/* GRAPHICS BOARD COMPONENT */
	private Point start;
	private Image[] images;
	private Image[] gameOverImages;
	private Image quads;

	private ImageIcon imgRules,imgCredits;
	private JLabel rulesLabel,creditsLabel;
	private Image emptyPiece;
	private Image[][] board;
	private Rectangle[] quadrants;
	private Rectangle[][] positions;
	private Image[] pieceImages;
	private Image winning_murble;
	private Object[] options = { "Yes, Return Game", "No way! u are too Strong" };
	private Icon dialogImage;

	/* GAME LOGIC COMPONENT */
	private GameSettings gameSettings;
	private GameMessage gameMessage;
	private GameGUI gui;
	private Move newMove;
	private Move graphicMove;
	private MouseHandler mouseHandler;
	private MouseMotionHandler mouseMotionHandler;

	/* GAME CONSTANTS */
	private final boolean BLACK = true;
	private final int BORDER = 55;
	private final int TOP_OFFSET = 95;
	private final int NO_ROTATING_QUAD = -1;
	private final int QUAD_OFFSET = 20;
	private final int IMAGE_SIZE = 55;

	/* ATOMIC TYPES */
	private int width;
	private int height;
	private int rotatingQuad;
	private int angle;
	private int gameType;
	private int gameStatus;
	private boolean currentPlayer;
	private boolean needToRotate;
	private boolean humanHasNotMoved;
	private int playAgain;
	private boolean IAisMoving;
	private boolean restart;
	private boolean playngMode;

	public GameGUI(GameMessage gameMessage, GameSettings gameSettings,
			boolean testMode) {
		this.gameMessage = gameMessage;
		this.gameSettings = gameSettings;
		this.gameStatus = gameSettings.getStatus();
		this.gameType = gameSettings.getMode();
		this.currentPlayer = BLACK;
		this.humanHasNotMoved = true;
		this.IAisMoving = !gameSettings.isFirstPlayer();
		this.gui = this;
		this.restart = false;
		this.dialogImage = new ImageIcon("images/gameIco.png");
		this.playngMode = testMode;
		initWindow();
		initBoard();
		initGameSettings();
		addMenus();
		addDrawingAreaListener();
		gameFrame.setVisible(true);
		drawingArea.repaint();
	}
 
	public void startGUI() {

		Message readMessage = new Message();
		Move readMove = new Move();

		while (gameStatus != Status.BLACK_WINS
				&& gameStatus != Status.WHITE_WINS && gameStatus != Status.DRAW
				&& !restart) {

			if (this.gameType == Status.GAME_PVC) {

				if (gameSettings.isFirstPlayer()) {

					//HUMAN moving first
					if (gameStatus == Status.GAME_ON && !restart) {

						IAisMoving = false;

						/** Waiting for Human Move **/
						while (humanHasNotMoved && !restart) {
							try {
								Thread.sleep(2000);
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
						if (!restart) {
							/** Reading message from Logic **/
							readMessage = gameMessage.readMessageFromLogic();

							/** Reading Game Status **/
							gameStatus = readMessage.getStatus();
							gameFrame.repaint();
						}
					}

					if (gameStatus == Status.GAME_ON && !restart) {

						/** Reading message from Logic **/
						readMessage = gameMessage.readMessageFromLogic();
						readMove = readMessage.getMove();

						/** Reading Game Status **/
						gameStatus = readMessage.getStatus();

						/** Reverting message to Graphics Convention **/
						graphicMove = modifyMoveForGUI(readMove);

						/** Drawing UpdatedMove **/
						drawSetMurble(graphicMove);
						aiDrawQuadrantRotation(graphicMove);
						drawQuadrantRotation(graphicMove);

						gameFrame.repaint();

						/** Updating Graphic Settings **/
						currentPlayer = !currentPlayer;
						humanHasNotMoved = true;


					}

				} else {
					//IA is moving first
					if (gameStatus == Status.GAME_ON && !restart) {

						/** Reading message from Logic **/
						readMessage = gameMessage.readMessageFromLogic();
						readMove = readMessage.getMove();

						/** Reading Game Status **/
						gameStatus = readMessage.getStatus();

						/** Reverting message to Graphics Convention **/
						graphicMove = modifyMoveForGUI(readMove);

						/** Drawing UpdatedMove **/
						drawSetMurble(graphicMove);
						aiDrawQuadrantRotation(graphicMove);
						drawQuadrantRotation(graphicMove);

						/** Updating Graphic Settings **/
						currentPlayer = !currentPlayer;
						gameFrame.repaint();
					}

					System.out.println("GAME STATUS = " + gameStatus);
					if (gameStatus == Status.GAME_ON && !restart) {

						IAisMoving = false;

						/** Waiting for Human Move **/
						while (humanHasNotMoved && !restart) {
							try {
								Thread.sleep(2000);
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
						if (!restart) {
							/** Reading message from Logic **/
							readMessage = gameMessage.readMessageFromLogic();
							/** Reading Game Status **/
							gameStatus = readMessage.getStatus();
							gameFrame.repaint();
							humanHasNotMoved = true;
						}
					}
				}

			} else if (this.gameType == Status.GAME_CVC) {

				if (gameStatus == Status.GAME_ON && !restart) {
					IAisMoving = true;

					/** Reading message from Logic **/
					readMessage = gameMessage.readMessageFromLogic();
					readMove = readMessage.getMove();

					/** Reading Game Status **/
					gameStatus = readMessage.getStatus();

					/** Reverting message to Graphics Convention **/
					graphicMove = modifyMoveForGUI(readMove);

					/** Drawing UpdatedMove **/
					drawSetMurble(graphicMove);
					aiDrawQuadrantRotation(graphicMove);
					drawQuadrantRotation(graphicMove);

					currentPlayer = !currentPlayer;
					gameFrame.repaint();
				}

			} else {

				if (!restart) {
					IAisMoving = false;
					/** Reading Game Status **/
					readMessage = gameMessage.readMessageFromLogic();
					gameStatus = readMessage.getStatus();
					System.out.println(gameStatus);
				}
			}
		}

		if (!restart) {
			readMessage = gameMessage.readMessageFromLogic();
			gameStatus = readMessage.getStatus();

			if (gameStatus != Status.DRAW) {
				drawWinningSet(readMessage.getWinningSet());
			} else {
				drawWinningSet(readMessage.getWinningSet());
				readMessage = gameMessage.readMessageFromLogic();
				drawWinningSet(readMessage.getWinningSet());
			}
		}

		if (playngMode) {
			if (!restart) {
				playAgain = JOptionPane.showOptionDialog(gameFrame,
						"             Play Again?", "End Game",
						JOptionPane.YES_NO_OPTION,
						JOptionPane.QUESTION_MESSAGE, dialogImage, options,
						options[0]);

				if (playAgain == JOptionPane.NO_OPTION) {
					gameSettings.setNewGame(false);
				} else {
					destroyWindow();
				}
			}
		} 

		destroyWindow();

	}

	private void addDrawingAreaListener() {
		drawingArea.addMouseListener(mouseHandler);
		drawingArea.addMouseMotionListener(mouseMotionHandler);
	}

	private void initGameSettings() {
		gameStatus = gameSettings.getStatus();
		rotatingQuad = NO_ROTATING_QUAD;
		currentPlayer = BLACK;
		needToRotate = false;
		angle = 0;
		newMove = new Move();
		newMove.setClockwise(false);
		newMove.setRow(-1);
		newMove.setColumn(-1);
	}

	private void initWindow() {
		gameFrame = new JFrame("Pentago");
		gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gameFrame.setResizable(false);
		gameFrame.setSize(new Dimension(690, 550));
		gameFrame.setLocation(120, 20);
		gameFrame.setIconImage(new ImageIcon("images/gameIco.png").getImage());
		gameFrame.setLocationRelativeTo(null);
		
		rules = new JFrame("Game Rules");
		rules.setSize(200, 400);
		imgRules = new ImageIcon("images/rules.png");
		rulesLabel = new JLabel(imgRules);
		rules.add(rulesLabel);
		rules.pack();
		rules.setResizable(false);
		
		credits = new JFrame("Credits");
		credits.setSize(300,200);
		imgCredits = new ImageIcon("images/credits.png");
		creditsLabel = new JLabel(imgCredits);
		credits.add(creditsLabel);
		credits.pack();
		credits.setResizable(false);
		
		drawingArea = new DrawingPanel();
		gameFrame.add(drawingArea, BorderLayout.CENTER);

		images = new Image[4];
		images[0] = new ImageIcon("images/pentagoMainBG.png").getImage();
		images[1] = new ImageIcon("images/boardBG.png").getImage();
		images[2] = new ImageIcon("images/playerConsole.png").getImage();
		images[3] = new ImageIcon("images/gameConsole.png").getImage();

		quads = new ImageIcon("images/Quadrant1&4BG.png").getImage();

		gameOverImages = new Image[5];

		gameOverImages[0] = new ImageIcon("images/black_wins.png").getImage();
		gameOverImages[1] = new ImageIcon("images/white_wins.png").getImage();
		gameOverImages[2] = new ImageIcon("images/draw.png").getImage();
		gameOverImages[3] = new ImageIcon("images/illegal_move.jpg").getImage();
		gameOverImages[4] = new ImageIcon("images/error.jpg").getImage();
	}

	private void initBoard() {
		positions = new Rectangle[6][6];

		pieceImages = new Image[6];
		pieceImages[0] = new ImageIcon("images/v2playerPieceQ1&4.png")
		.getImage();
		pieceImages[1] = new ImageIcon("images/v2player2PieceQ1&4.png")
		.getImage();
		emptyPiece = new ImageIcon("images/emptyPieceQ1&4.png").getImage();
		winning_murble = new ImageIcon("images/winning_murble.png").getImage();

		board = new Image[6][6];

		width = IMAGE_SIZE;
		height = IMAGE_SIZE;

		quadrants = new Rectangle[4];
		quadrants[0] = new Rectangle(53, TOP_OFFSET, (3 * width) - 5,
				(3 * height) - 5);
		quadrants[1] = new Rectangle(53 + ((3 * width) - 5) + 25, TOP_OFFSET,
				(3 * width) - 5, (3 * height) - 5);
		quadrants[2] = new Rectangle(53, (TOP_OFFSET + (3 * height) + 20),
				3 * width - 5, (3 * height) - 5);
		quadrants[3] = new Rectangle(53 + ((3 * width) - 5) + 25, (TOP_OFFSET
				+ (3 * height) + 20), (3 * width) - 5, (3 * width) - 5);

		for (int row = 0; row < positions.length; row++) {
			for (int col = 0; col < positions[row].length; col++) {
				int nextX = col * width + BORDER + (int) (Math.ceil(col / 3))
						* QUAD_OFFSET;
				int nextY = height * row + TOP_OFFSET
						+ (int) (Math.ceil(row / 3)) * QUAD_OFFSET;

				board[row][col] = emptyPiece;
				positions[row][col] = new Rectangle(nextX, nextY, width - 5,
						height - 5);
			}
		}
		mouseHandler = new MouseHandler();
		mouseMotionHandler = new MouseMotionHandler();
		drawingArea.repaint();
	}

	public void destroyWindow() {
		gameFrame.setVisible(false);
	}

	public void addMenus() {
		JMenuBar menuBar = new JMenuBar();
		JMenu gameMenu, helpMenu;
		JMenuItem newGame, exitGame;
		JMenuItem howToPlay, about;

		gameMenu = new JMenu("Game");
		newGame = new JMenuItem("New Game");
		newGame.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				restart = true;
			}

		});

		exitGame = new JMenuItem("Exit");
		exitGame.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {

				if (gameStatus > Status.GAME_OFF) {
					System.exit(0);
				} else {
					int answer = JOptionPane.showConfirmDialog(null,
							"Are you sure you want to exit? ", "",
							JOptionPane.YES_NO_OPTION);
					if (answer == JOptionPane.YES_OPTION) {
						System.exit(0);
					}
				}
			}
		});

		helpMenu = new JMenu("Help");
		howToPlay = new JMenuItem("Rules");
		howToPlay.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evnt) {
				if(!rules.isVisible()){
					rules.setVisible(true);
				}
			}
		});
		about = new JMenuItem("Credits");
		about.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evnt) {
				if(!credits.isVisible()){
					credits.setVisible(true);
				}
			}
		});

		gameFrame.setJMenuBar(menuBar);
		menuBar.add(gameMenu);
		gameMenu.add(newGame);
		gameMenu.addSeparator();
		gameMenu.add(exitGame);
		menuBar.add(helpMenu);
		helpMenu.add(howToPlay);
		helpMenu.addSeparator();
		helpMenu.add(about);
	}

	public int selectedQuadrant(Point point) {
		for (int currentQuad = 0; currentQuad < quadrants.length; currentQuad++) {
			if (quadrants[currentQuad].contains(point))
				return currentQuad;
		}
		return -1;
	}

	public Point getCentre(int rotatingQuadrant) {
		Point centre = new Point(quadrants[rotatingQuadrant].x
				+ quadrants[rotatingQuadrant].width / 2,
				quadrants[rotatingQuadrant].y
				+ quadrants[rotatingQuadrant].height / 2);

		return centre;
	}

	public Point point2cell(Point pos) {
		Point currPoint = new Point(-1, -1);
		for (int row = 0; row < positions.length; row++) {
			for (int col = 0; col < positions[row].length; col++) {
				if (positions[row][col].contains(pos)) {
					currPoint.x = col;
					currPoint.y = row;
				}
			}
		}
		return currPoint;
	}

	public void modifyMoveForLogic(Move move) {
		int temp = 0;
		temp = move.row();
		move.setRow(move.column() + 1);
		move.setColumn(temp + 1);
		move.setElement(move.element() + 1);
	}

	public Move modifyMoveForGUI(Move move) {
		int temp = 0;
		Move adjustedMove = new Move();
		temp = move.row();
		adjustedMove.setRow(move.column() - 1);
		adjustedMove.setColumn(temp - 1);
		adjustedMove.setElement(move.element() - 1);
		adjustedMove.setBlack(move.black());
		adjustedMove.setClockwise(move.clockwise());
		return adjustedMove;
	}

	public void draw(Graphics2D g, int rotatingQuadrant) {

		for (int row = 0; row < 6; row++)
			for (int col = 0; col < 6; col++) {

				int nextX = col * width + BORDER + (int) (Math.ceil(col / 3))
						* QUAD_OFFSET;
				int nextY = height * row + TOP_OFFSET
						+ (int) (Math.ceil(row / 3)) * QUAD_OFFSET;

				if (rotatingQuadrant == NO_ROTATING_QUAD
						|| !quadrants[rotatingQuadrant].contains(new Point(
								nextX, nextY))) {

					g.drawImage(board[row][col], nextX, nextY, width - 5,
							height - 5, null);

				}
			}

		if (rotatingQuad != NO_ROTATING_QUAD) {
			Point centre = new Point(quadrants[rotatingQuadrant].x
					+ quadrants[rotatingQuadrant].width / 2,
					quadrants[rotatingQuadrant].y
					+ quadrants[rotatingQuadrant].height / 2);

			g.rotate(Math.toRadians(angle), centre.x, centre.y);

			for (int row = 0; row < 6; row++)
				for (int col = 0; col < 6; col++) {
					int nextX = col * width + BORDER
							+ (int) (Math.ceil(col / 3)) * QUAD_OFFSET;
					int nextY = height * row + TOP_OFFSET
							+ (int) (Math.ceil(row / 3)) * QUAD_OFFSET;

					if (quadrants[rotatingQuadrant].contains(new Point(nextX,
							nextY))) {

						g.drawImage(board[row][col], nextX, nextY, width - 5,
								height - 5, null);

					}

				}
		}

	}

	public void drawSetMurble(Move move) {

		int player;

		if (currentPlayer)
			player = 0;
		else
			player = 1;

		board[move.row()][move.column()] = pieceImages[player];
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		drawingArea.repaint();

	}

	public void drawWinningSet(ArrayList<Move> winningset) {

		for (Move move : winningset) {
			board[move.row()][move.column()] = winning_murble;
		}
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		drawingArea.repaint();

	}

	public void aiDrawQuadrantRotation(Move move) {

		angle = 0;
		rotatingQuad = move.element();

		System.out.println("ROTATING QUAD = " + rotatingQuad);
		for (int i = 0; i < 10; i++) {

			if (move.clockwise())
				angle += 9;
			else
				angle -= 9;
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			drawingArea.repaint();

		}
		rotatingQuad = NO_ROTATING_QUAD;
	}

	public void drawQuadrantRotation(Move move) {

		Image[][] rotateboard = new Image[6][6];
		int startX = 0, startY = 0, endX = 0, endY = 0, clockwiseRotation = 0, counterClockWise = 0, counterClockWiseRefresh = 0, rotatingCol = 0;
		int graphicsElement = move.element();
		// setting parameters sub rotation
		if (graphicsElement == 0) {
			clockwiseRotation = 0;
			counterClockWise = 0;
			counterClockWiseRefresh = 0;
			rotatingCol = 3;
			startX = 0;
			startY = 0;
			endX = 3;
			endY = 3;
		} else if (graphicsElement == 1) {
			clockwiseRotation = 3;
			counterClockWise = 0;
			counterClockWiseRefresh = 0;
			rotatingCol = 6;
			startX = 0;
			startY = 3;
			endX = 3;
			endY = 6;
		} else if (graphicsElement == 2) {
			clockwiseRotation = 0;
			counterClockWise = 3;
			counterClockWiseRefresh = 3;
			rotatingCol = 6;
			startX = 3;
			startY = 0;
			endX = 6;
			endY = 3;
		} else {
			clockwiseRotation = 3;
			counterClockWise = 3;
			counterClockWiseRefresh = 3;
			rotatingCol = 9;
			startX = 3;
			startY = 3;
			endX = 6;
			endY = 6;
		}

		if (move.clockwise()) {
			for (int i = startX; i < endX; ++i) {
				for (int j = startY; j < endY; ++j) {
					rotateboard[i][j] = board[rotatingCol - j - 1][clockwiseRotation];
				}
				clockwiseRotation++;
			}

		} else {
			for (int i = startX; i < endX; ++i) {
				for (int j = startY; j < endY; ++j) {
					rotateboard[i][j] = board[counterClockWise][rotatingCol - i
					                                            - 1];
					counterClockWise++;
				}
				counterClockWise = counterClockWiseRefresh;
			}
		}

		for (int i = startX; i < endX; ++i) {
			for (int j = startY; j < endY; ++j) {
				board[i][j] = rotateboard[i][j];
			}
		}
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private class DrawingPanel extends JPanel {

		private static final long serialVersionUID = 1L;

		public DrawingPanel() {
			setBackground(new Color(39, 33, 24));
			setPreferredSize(new Dimension(690, 620));
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2d = (Graphics2D) g;
			g2d.addRenderingHints(new RenderingHints(
					RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON));

			/* draw board */
			g2d.drawImage(images[0], 0, 0, 690, 500, this);
			g2d.drawImage(images[1], 33, 74, 390, 391, this);
			//g2d.drawImage(images[2], 451, 74, 186, 187, this);
			g2d.drawImage(images[3], 451, 275, 186, 150, this);

			if (gameStatus < Status.GAME_ON) {
				// don't draw game area
			} else if (gameStatus == Status.GAME_ON) {

				/* draw quadrants */
				g2d.drawImage(quads, 45, 88, 177, 176, this);
				g2d.drawImage(quads, 232, 88, 177, 176, this);
				g2d.drawImage(quads, 45, 274, 177, 176, this);
				g2d.drawImage(quads, 232, 274, 177, 176, this);

				g2d.setFont(new Font("Tahoma", Font.BOLD, 24));
				g2d.setColor(new Color(39, 33, 24));
				if (currentPlayer)
					g2d.drawString(" BLACK player ", 460, 330);
				else
					g2d.drawString(" WHITE player ", 460, 330);

				g2d.drawString(" moves", 460, 355);

				draw(g2d, rotatingQuad);
			} else {
				int gameOverIndex = -1;
				switch (gameStatus) {
				case Status.BLACK_WINS:
					gameOverIndex = 0;
					break;
				case Status.WHITE_WINS:
					gameOverIndex = 1;
					break;
				case Status.DRAW:
					gameOverIndex = 2;
					break;
				case Status.ILLEGAL_MOVE:
					gameOverIndex = 3;
					break;
				case Status.ERROR:
					gameOverIndex = 4;
					break;
				}

				/* draw quadrants */
				g2d.drawImage(quads, 45, 88, 177, 176, this);
				g2d.drawImage(quads, 232, 88, 177, 176, this);
				g2d.drawImage(quads, 45, 274, 177, 176, this);
				g2d.drawImage(quads, 232, 274, 177, 176, this);
				g2d.drawImage(gameOverImages[gameOverIndex], 460, 150, 170, 85, this);

				g2d.setFont(new Font("Tahoma", Font.BOLD, 20));
				g2d.setColor(new Color(39, 33, 24));
				g2d.drawString(" Last move: ", 460, 330);
				switch(gameType){
				case Status.GAME_PVP:
					g2d.drawString(newMove.toString(), 460, 350);
					break;
				case Status.GAME_CVC:
					g2d.drawString(graphicMove.toString(), 460, 350);
					break;
				case Status.GAME_PVC:
					if(gameStatus == Status.BLACK_WINS && gameSettings.isFirstPlayer()
					|| gameStatus == Status.WHITE_WINS && !gameSettings.isFirstPlayer())
						g2d.drawString(newMove.toString(), 460, 350);
					else
						g2d.drawString(graphicMove.toString(), 460, 350);
					break;
				}

				draw(g2d, rotatingQuad);

			}

		}

	}

	private class MouseHandler extends MouseAdapter {
		public void mousePressed(MouseEvent event) {
			int row, col;

			if (gameStatus == Status.GAME_ON && !needToRotate) {
				if (IAisMoving) {
					return;
				}
				row = point2cell(event.getPoint()).y;
				col = point2cell(event.getPoint()).x;
				System.out.println(row + " " + col);
				try {
					if (board[row][col].equals(emptyPiece)) {
						newMove.setBlack(currentPlayer);
						newMove.setColumn(col);
						newMove.setRow(row);
						needToRotate = true;

						drawSetMurble(newMove);
					} else {

						// print error...illegal move
					}
				} catch (Exception e) {

				}
			} else {

				if (IAisMoving) {
					return;
				}
				// l'utente deve ruotare
				rotatingQuad = selectedQuadrant(event.getPoint());
				newMove.setElement(rotatingQuad);
			}

			start = event.getPoint();
			gameFrame.repaint();
			System.out.println(newMove.row() + " " + newMove.column());

		}

		public void mouseReleased(MouseEvent event) {
			if (gameStatus < Status.GAME_ON) {
				if (IAisMoving) {
					return;
				}

				if (!needToRotate) {
				}
			}

			rotatingQuad = -1;
			angle = 0;
			// newMove = null;
			gameFrame.repaint();
		}

	}

	private class MouseMotionHandler extends MouseMotionAdapter {
		public void mouseMoved(MouseEvent event) {
			if (gameStatus == Status.GAME_ON) {
				if (IAisMoving) {
					return;
				}
				drawingArea.repaint();
			}
		}

		public void mouseDragged(MouseEvent event) {
			Message message = new Message();

			if (gameStatus == Status.GAME_ON) {
				if (IAisMoving) {
					return;
				}

				if (rotatingQuad == NO_ROTATING_QUAD)
					return;

				if (needToRotate) {
					Point centre = getCentre(rotatingQuad);

					int firstX = start.x - centre.x;
					int firstY = start.y - centre.y;

					double firstAngle = (Math.toRadians(Math.atan2(firstY,
							firstX)));
					Point end = event.getPoint();

					int lastX = end.x - centre.x;
					int lastY = end.y - centre.y;

					double lastAngle = (Math
							.toRadians(Math.atan2(lastY, lastX)));

					if (gameStatus == Status.GAME_ON) {
						if (lastAngle > firstAngle) {
							angle += 8;
						} else {
							angle -= 8;
						}
					}

					if (angle >= 90) {
						angle = 90;
						newMove.setClockwise(true);
						rotatingQuad = NO_ROTATING_QUAD;
						needToRotate = false;
						drawQuadrantRotation(newMove);
						modifyMoveForLogic(newMove);
						message.setMove(newMove);
						gameMessage.sendMessageToLogic(message);
						humanHasNotMoved = false;
						// change to next player
						currentPlayer = !currentPlayer;
						IAisMoving = true;
					} else if (angle <= -90) {
						angle = -90;
						newMove.setClockwise(false);
						rotatingQuad = NO_ROTATING_QUAD;
						needToRotate = false;
						drawQuadrantRotation(newMove);
						modifyMoveForLogic(newMove);
						message.setMove(newMove);
						gameMessage.sendMessageToLogic(message);
						humanHasNotMoved = false;
						// change to next player
						currentPlayer = !currentPlayer;
						IAisMoving = true;
					}

					start = event.getPoint();
					gameFrame.repaint();

				}

			}
		}
	}

}
